#include <stdio.h>

int main(int argc, const char *argv[])
{
	// 当执行到定义变量的语句时
	// 操作系统会根据变量的类型 给变量分配内存空间
	int a = 10;
	
	// 使用 & 可以获取变量占用的内存空间的地址(首地址)
	// printf 的 %p 可以打印地址(十六进制格式)
	printf("&a = %p\n", &a);

	// 可以定义指针来保存变量的地址
	int *p = &a;
	printf("p = %p\n", p);
	// 当指针保存了某个变量的地址后 我们称之为指针指向该变量
	
	// 指针指向变量后 就可以通过指针访问变量所在的内存空间了
	*p = 1234; // 写操作
	printf("*p = %d  a = %d\n", *p, a); // 1234  读操作

	// 地址本身也是一个整数 但是注意 不要使用普通的变量来保存地址
	//long value = &a;
	//printf("value = %#lx\n", value); // 保存是可以保存的
	//*value = 200; // 但是不能通过普通变量访问内存 因为不能取 * 操作
	
	// 指针也是变量 可以被修改(指向可以修改)
	int b = 200;
	p = &b;
	printf("&b = %p  p = %p\n", &b, p); // 一样的

	// 在应用层开发中:指针只能指向已经分配了地址
	//int *p2 = 0x56AB12;
	//*p2 = 100; // 结果是不可预知的

	// 一行可以定义多个指针变量 但是要注意
	// 1.这种写法 p3 是指针  p4就是一个普通的int变量
	int *p3, p4;
	p3 = &a;
	//p4 = &b; // 警告
	// 2.这种写法 p5 和 p6 才都是指针变量
	int *p5, *p6;
	p5 = &a;
	p6 = &b;

	// 定义指针时 如果没有初始化 里面也是随机值(表示一个随机地址)
	// 这种指针 我们称之为 野指针--对程序是有害的
	//int *p7;
	//*p7 = 100; // 对野指针取*操作结果是不可预知的
	
	// 在头文件中有如下宏定义
	// #define NULL ((void *)0)
	// 所以定义指针时如果不知道用谁初始化 就用 NULL 来初始化
	// 这种指针我们称之为  空指针
	// 对空指针取 * 操作 一定是段错误
	int *p8 = NULL;
	printf("p8 = %p\n", p8); // nil
	// *p8 = 100; // 段错误

	return 0;
}
